home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 7
/
Apprentice-Release7.iso
/
Source Code
/
Pascal
/
Snippets
/
PNL Libraries
/
MyHistory.p
< prev
next >
Wrap
Text File
|
1996-08-21
|
6KB
|
246 lines
unit MyHistory;
{ Edit history}
{ 9 Dec 95 pnl Original}
{ 8 Apr 96 jc Add bits for marking which downstream servers were offered this message }
{ 9 Apr 96 jc Adjust ReadEntry to account for longer EntryRecord }
{11 Apr 96 jc Fix bug in markMsgSent (reading too many bytes & clobbering data on write }
{14 Apr 96 jc Added markMsgNotSent }
{25 May 96 jc Added HistoryAfterStep }
interface
uses
Types, Files;
const
H_Null = $12345678;
H_FromStart = $80000000;
function HistoryCreate (var fs: FSSpec): OSErr;
{ You should create the file before calling this using FSpCreate. Any existing data will be destroyed. }
function HistoryOpen (var fs: FSSpec; var refnum: longint): OSErr;
function HistoryFlush (refnum: longint): OSErr;
function HistoryClose (refnum: longint): OSErr;
function HistoryAdd (refnum: longint; data: Str255): OSErr;
function HistoryAfter (refnum: longint; time: longint; var id: longint): OSErr;
function HistoryAfterStep(refnum: longint; time: longint; var id: longint; var maxtime: integer): OSErr;
function HistoryNext (refnum: longint; var id: longint; var time: longint; var offered: longint; var data: Str255): OSErr;
function HistoryExpire (refnum: longint; time: longint): OSErr;
function msgSentP(offered: longint; idx: integer): boolean;
procedure markMsgSent(refnum: longint; pos: longint; idx: integer);
procedure markMsgNotSent(refnum: longint; pos: longint; idx: integer);
implementation
uses
Errors, OSUtils,
MyFileSystemUtils, MyMemory, MyMathUtils;
{ File format: }
{ sequence of entries }
{ Entry format: }
{ time:longint }
{ offered: longint }
{ data:PString }
{ zero:byte }
{$PUSH}
{$ALIGN MAC68K}
const
EROverhead = 4+4+1; { this must be adjusted to match the position of the 1st byte of Data in the HistoryRecord }
type
HistoryRecord = record
time: longint; { time message added }
offered: longint; { bit mask of servers offered this message }
data: Str255; { message ID }
zero: byte;
end;
{$ALIGN RESET}
{$POP}
function HistoryCreate (var fs: FSSpec): OSErr;
var
err, oerr: OSErr;
rn: integer;
begin
err := FSpOpenDF(fs, fsRdWrPerm, rn);
if err = noErr then begin
err := SetEOF(rn, 0);
oerr := FSClose(rn);
if err = noErr then
err := oerr;
end;
HistoryCreate := err;
end;
function HistoryOpen (var fs: FSSpec; var refnum: longint): OSErr;
var
err, junk: OSErr;
rn: integer;
begin
err := FSpOpenDF(fs, fsRdWrPerm, rn);
if err = noErr then begin
if err <> noErr then begin
junk := FSClose(rn);
end;
end;
refnum := rn;
if err <> noErr then begin
refnum := H_Null;
end;
HistoryOpen := err;
end;
function HistoryFlush (refnum: longint): OSErr;
var
err: OSErr;
pb: ParamBlockRec;
begin
pb.ioRefNum := refnum;
err := PBFlushFileSync(@pb);
HistoryFlush := err;
end;
function HistoryClose (refnum: longint): OSErr;
var
err: OSErr;
begin
if refnum <> H_Null then begin
err := FSClose(refnum);
end;
HistoryClose := err;
end;
function HistoryAdd (refnum: longint; data: Str255): OSErr;
var
err: OSErr;
er: HistoryRecord;
begin
MFill(@er, SizeOf(er), 0);
GetDateTime(er.time);
er.data := data;
er.offered := 0;
err := MyFSWriteAt(refnum, fsFromLEOF, 0, EROverhead + length(data), @er);
HistoryAdd := err;
end;
function ReadEntry (refnum: longint; var pos: longint; var entry: HistoryRecord): OSErr;
var
err: OSErr;
begin
err := MyFSReadAt(refnum, pos, EROverhead, @entry); { read enough of the record to get string length }
if err = noErr then begin
err := MyFSReadAt(refnum, pos, EROverhead + length(entry.data), @entry); { now read entire record }
end;
if err = noErr then begin
pos := pos + EROverhead + length(entry.data);
end;
ReadEntry := err;
end;
function HistoryAfter (refnum: longint; time: longint; var id: longint): OSErr;
var
err: OSErr;
pos: longint;
entry: HistoryRecord;
begin
pos := 0;
repeat
id := pos;
err := ReadEntry(refnum, pos, entry);
until (err <> noErr) or (entry.time >= time);
HistoryAfter := err;
end;
function HistoryAfterStep(refnum: longint; time: longint; var id: longint; var maxtime: integer): OSErr;
var
err: OSErr;
pos: longint;
entry: HistoryRecord;
start, now: longint;
begin
pos := id;
GetDateTime(start);
repeat
id := pos;
err := ReadEntry(refnum, pos, entry);
GetDateTime(now);
until (err <> noErr) or (entry.time >= time) or ((start+maxtime)<now);
if ((start+maxtime)<now) then maxtime := -maxtime; { let caller know it timed out }
HistoryAfterStep := err;
end;
function HistoryNext (refnum: longint; var id: longint; var time: longint; var offered: longint; var data: Str255): OSErr;
var
err: OSErr;
entry: HistoryRecord;
begin
err := ReadEntry(refnum, id, entry);
time := entry.time;
offered := entry.offered;
data := entry.data;
HistoryNext := err;
end;
function HistoryExpire (refnum: longint; time: longint): OSErr;
var
err: OSErr;
src, dst, len, cnt: longint;
buffer: packed array[1..8192] of Byte;
begin
err := HistoryAfter(refnum, time, src);
if err = noErr then begin
err := GetEOF(refnum, len);
if err = noErr then begin
len := len - src;
dst := 0;
while (err = noErr) & (len > 0) do begin
cnt := Min(len, SizeOf(buffer));
err := MyFSReadAt(refnum, src, cnt, @buffer);
if err = noErr then begin
err := MyFSWriteAt(refnum, fsFromStart, dst, cnt, @buffer);
end;
src := src + cnt;
dst := dst + cnt;
len := len - cnt;
end;
end;
end else if err = eofErr then begin
err := SetEOF(refnum, 0);
end;
HistoryExpire := err;
end;
function msgSentP(offered: longint; idx: integer): boolean;
begin
msgSentP := BTst(offered, idx);
end;
procedure markMsgSent(refnum: longint; pos: longint; idx: integer);
var
err: OSErr;
entry: HistoryRecord;
begin
err := MyFSReadAt(refnum, pos, EROverhead, @entry);
if err = noErr then begin
BSet(entry.offered, idx);
err := MyFSWriteAt(refnum, fsFromStart, pos, EROverhead, @entry);
end;
end;
procedure markMsgNotSent(refnum: longint; pos: longint; idx: integer);
var
err: OSErr;
entry: HistoryRecord;
begin
err := MyFSReadAt(refnum, pos, EROverhead, @entry);
if err = noErr then begin
BClr(entry.offered, idx);
err := MyFSWriteAt(refnum, fsFromStart, pos, EROverhead, @entry);
end;
end;
end.